#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <functional>
using namespace std;


class Date
{
public:
	Date(int year = 2000, int month = 1, int day = 1)
		:_year(year)
		,_month(month)
		,_day(day)
	{}


	int _year;
	int _month;
	int _day;
};
namespace gy
{
	template<class T>
	class shared_ptr
	{
	public:
		shared_ptr(T* ptr)
			:_ptr(ptr)
			,_pcount(new int(1))
		{}

		template<class D>
		shared_ptr(T* ptr, D func)
			: _ptr(ptr)
			, _pcount(new int(1))
			, _func(func)
		{}

		shared_ptr(const shared_ptr& sp)
			:_ptr(sp._ptr)
			,_pcount(sp._pcount)
			, _func(sp._func)
		{
			++(*_pcount);
		}

		shared_ptr& operator=(const shared_ptr& sp)
		{
			if (_ptr != sp._ptr)
			{
				/*if (--(*_pcount) == 0)
				{
					delete _ptr;
					delete _pcount;
				}*/
				this->~shared_ptr();

				_ptr = sp._ptr;
				_pcount = sp._pcount;
				_func = sp._func;
				++(*_pcount);
			}
			return *this;
		}

		T& operator*()
		{
			return *_ptr;
		}

		T* operator->()
		{
			return _ptr;
		}
		

		~shared_ptr()
		{
			if (--(*_pcount) == 0)
			{
				_func(_ptr);
				//delete _ptr;
				delete _pcount;
			}
		}

	private:
		T* _ptr;
		int* _pcount;
		function<void(T*)> _func = [](T* sp) {delete sp; };
	};

}

int main()
{
	/*gy::shared_ptr<int> sp1(new int(1));
	*sp1 = 2;*/

	//gy::shared_ptr<Date> sp2(new Date(2025));
	//gy::shared_ptr<Date> sp3 = sp2;
	//sp2->_month = 6;
	//sp3->_day = 15;

	//gy::shared_ptr<Date> sp4(new Date);
	//sp2 = sp4;

	int* a = new int[5] {1,1,1,1,1};
	gy::shared_ptr<int> sp5(a, [](int* s) {delete[] s; });

	
	return 0;
}